package pers.vic.test.rpc.framework;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;

import java.io.IOException;
import java.io.InputStream;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.util.List;
import java.util.Properties;

/**
 * 框架入口
 *
 * @author Vic.xu
 * @date 2021/08/10
 */
public class RpcFactory {

    /*
     * 初始化过程：
     * 固定逻辑：
     * 在classpath下，提供配置文件rpc.properties;
     * 配置文件结构固化：
     * registry.ip = 服务端地址，默认为localhost
     * registry.port = 服务端port，默认为9090
     * zk.server = zk地址，默认为localhost:2181
     * zk.sessionTimeout = 连接回话超时时间，默认为10000
     */

    private static final Properties CONFIG = new Properties();

    // 连接对象
    private static final ZkConnection CONNECT;

    // 注册器地址
    private static final RpcRegistry REGISTRY;

    static {
        // 获取输入文件输入流
        InputStream in = RpcFactory.class.getClassLoader().getResourceAsStream("rpc.properties");
        try {
            CONFIG.load(in);
            String serverIp =
                    CONFIG.getProperty("registry.ip") == null ? "localhost" : CONFIG.getProperty("registry.ip");
            int serverPort = CONFIG.getProperty("registry.port") == null ? 9090
                    : Integer.parseInt(CONFIG.getProperty("registry.port"));
            String zkServer =
                    CONFIG.getProperty("zk.server") == null ? "localhost:2181" : CONFIG.getProperty("zk.server");
            int sessionTimeout = CONFIG.getProperty("zk.sessionTimeout") == null ? 30000
                    : Integer.parseInt(CONFIG.getProperty("zk.sessionTimeout"));

            // 创建练剑对象
            CONNECT = new ZkConnection(zkServer, sessionTimeout);
            // 创建并初始化注册器对象
            REGISTRY = new RpcRegistry();
            REGISTRY.setIp(serverIp);
            REGISTRY.setPort(serverPort);
            REGISTRY.setZkConnection(CONNECT);

            // 创建RMI的注册器
            LocateRegistry.createRegistry(serverPort);
            // LocateRegistry.getRegistry(serverPort);

            // 初始化zk中的父节点 /vic/rpc/
            List<String> children = CONNECT.getConnction().getChildren("/", false);
            if (!children.contains("vic")) {
                CONNECT.getConnction().create("/vic", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
            List<String> list = CONNECT.getConnction().getChildren("/vic", false);
            if (!list.contains("rpc")) {
                CONNECT.getConnction().create("/vic/rpc", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }

            /*
             * 自动初始化：TODO
             *   UserService userService = new UserServiceImpl();
             *   RpcFactory.registerService(UserService.class, userService);
             */

        } catch (Exception e) {
            // 初始化异常抛出，终止虚拟机
            throw new ExceptionInInitializerError(e);

        }
    }

    // 提供一个快速注册服务和创建客户端代理对象的方法
    public static void registerService(Class<? extends Remote> serviceInterface, Remote serviceObject)
            throws KeeperException, InterruptedException, IOException {
        REGISTRY.regstryService(serviceInterface, serviceObject);
    }

    public static <T extends Remote> T getServiceProxy(Class<? extends Remote> serviceInterface)
            throws KeeperException, InterruptedException, IOException, NotBoundException {
        return REGISTRY.getServiceProxy(serviceInterface);
    }

}
